package com.ttbj.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alipay.api.internal.util.StringUtils;
import com.ttbj.constant.PlatFormErrorCode;
import com.ttbj.exception.WebException;
import com.ttbj.util.jsr.Jsr303Util;

/**
 * 判断工具类
 * 
 * @author Medivh
 */
public class Assert {

	private static final Logger log = LoggerFactory.getLogger(Assert.class);
	private static final String NULL_MASSAGE = "不合法、原因为空";
	private static final String NULL_FEILD = "出现错误、原因：验证字段参数不存在传入空或是null,验证字段参数";

	/**
	 * 基于Jsr断言对象字段是否为空
	 * 
	 * @param param
	 * @throws WebException
	 */
	public static void assertFiledJsr(Object obj) throws WebException {
		boolean isAssert = true;
		if (null == obj) {
			isAssert = false;
		}
		String check = Jsr303Util.check(obj);
		if (!isEmpty(check)) {
			isAssert = false;
		}
		if (!isAssert) {
			ResultUtil.throwExcepion(ViewModelUtil.buildFailure(PlatFormErrorCode.PARAM_IS_NULL.code(), check));
		}
	}

 
	/**
	 * 断言对象和属性的非空
	 * 
	 * @param obj
	 *            判断的对象
	 * @param messageCode
	 *            统一管理提示key，null不需要使用统一管理提示.那么提示使用errorMessage
	 * @param error
	 *            管理台打印的异常提示，如果messageCode为null还需要作为提示使用,
	 *            值为null那么将默认无需抛出异常无需做任何处理。 注意:这里有个格式的问题。 格式：打印到控制台的异常信息,信息名
	 * @param fieldNames
	 *            需要判断的字段名字
	 * @throws Exception
	 */
	public static boolean assertNonNullField(Object obj, String error, Integer messageCode, Object[] objs, String... fieldNames) throws Exception {
		String[] fieldNameArray = fieldNames;
		if (null == fieldNameArray || fieldNameArray.length <= 0) {
			fieldErrorHandler(fieldNames, NULL_FEILD, null, null);
		}
		if (assertNonNullField(obj, fieldNames)) {
			return true;
		}
		return fieldErrorHandler(obj, error, messageCode, objs);
	}

	public static boolean assertNonNullField(Object obj, String error, String... fieldNames) throws Exception {
		return assertNonNullField(obj, error, null, null, fieldNames);
	}

	public static boolean assertNonNullField(Object obj, Integer messageCode, String... fieldNames) throws Exception {
		return assertNonNullField(obj, null, messageCode, null, fieldNames);
	}
	
 
	/**
	 * 非null判断
	 * 未优化的方式前期出现
	 * @param obj
	 * @param fileName
	 * @param messageCode
	 * @param objs
	 * @param errorMssage
	 *            格式例子：没有查询到寄件人信息，寄件人
	 * @throws WebException
	 */
	public static boolean assertNonNullObj(Object obj, int messageCode, Object[] objs, String errorMssage) throws WebException {
		return assertNonNullObj(obj, errorMssage, messageCode, objs);
	}

	/**
	 * 异常提示和错误码提示
	 * <为了隐藏实际的异常提示而采用的一种方式>
	 * 向用户反馈系统错误而实际是因为后台把不规范的参数提供给了后台而造成的错误
	 * 也可能是因为让异常一目了然
	 *  {比如undefined而造成的错误}
	 * @param obj
	 * @param messageCode
	 * @param errorMssage
	 * @return
	 * @throws WebException
	 */
	public static boolean assertNonNullObj(Object obj, int messageCode, String errorMssage) throws WebException {
		return assertNonNullObj(obj, errorMssage, messageCode, null);
	}

	/**
	 * 自定义返回提示
	 * 
	 * @param obj
	 * @param errorMssage
	 * @return
	 * @throws WebException
	 */
	public static boolean assertNonNullObj(Object obj, String errorMssage) throws WebException {
		return assertNonNullObj(obj, errorMssage, null, null);
	}

	/**
	 * 错误码返回提示
	 * 
	 * @param obj
	 * @param messageCode
	 * @return
	 * @throws WebException
	 */
	public static boolean assertNonNullObj(Object obj, int messageCode) throws WebException {
		return assertNonNullObj(obj, null, messageCode, null);
	}

	@SuppressWarnings("rawtypes")
	public static boolean isEmpty(Object s) {
		if (s instanceof String) {
			String str = (String) s;
			if (null == str || str.isEmpty()) {
				return true;
			}
		} else if (s instanceof Collection) {
			Collection collection = (Collection) s;
			if (null == collection || collection.isEmpty()) {
				return true;
			}
		} else {
			return true;
		}
		return false;
	}

	public static boolean assertThan0(Integer... cod) {
		if (null == cod || cod.length <= 0) {
			return false;
		}
		List<Integer> list = Arrays.stream(cod).filter(x -> x == null || x <= 0).collect(Collectors.toList());
		return null == list || list.isEmpty();
	}

	public static boolean assertNonNullField0(Object obj, String... fieldNonNulls) throws Exception {
		return assertNonNullField(obj, fieldNonNulls);
	}
	
	public static void assertNumeric(String arg, Integer messageCode) throws Exception{
		assertNumeric(arg, null, messageCode, null);
	}
	public static void assertNumeric(String arg, Integer messageCode,Object...ojs) throws Exception{
		assertNumeric(arg, null, messageCode, ojs);
	}
	public static boolean assertZero(Float fee) {
		if(null == fee ||  fee < 0.01f){
			return true;
		}
		return false;
	}
	
 


	/*------------------------------------------------------------------*/
	
	private static boolean assertNumeric(String arg, String error, Integer messageCode, Object[] objs) throws Exception{
		 if(isEmpty(arg) ||!StringUtils.isNumeric(arg)){
			 errorHandler(error, messageCode, objs);
			 return false;
		 }
		return true;
	} 

	// 异常处理
	private static boolean fieldErrorHandler(Object obj, String error, Integer messageCode, Object[] objs) throws WebException {
		if (isEmpty(error)) {
			error = ResourcesUtil.getValue("messages", messageCode + "");
		}
		String objName = null;
		if (error.contains(",")) {
			String[] errorSplit = error.split(",");
			objName = errorSplit == null || errorSplit.length < 2 ? obj.getClass().getName() : errorSplit[1];
			log.info(objName + "信息:{}", obj);
		} else {
			log.info(error);
		}

		if (null == messageCode) {
			ResultUtil.throwExcepion(ViewModelUtil.buildFailure(99999, error), error + NULL_MASSAGE);
		} else {
			ResultUtil.throwExcepion(ResultUtil.createFail("messages", messageCode, objs));
		}
		return false;
	}
	
	private static void errorHandler(String error, Integer messageCode, Object[] objs) throws WebException{
		if (isEmpty(error)) {
			error = ResourcesUtil.getValue("messages", messageCode + "");
		}
		if (null == messageCode) {
			ResultUtil.throwExcepion(ViewModelUtil.buildFailure(99999, error), error + NULL_MASSAGE);
		} else {
			ResultUtil.throwExcepion(ResultUtil.createFail("messages", messageCode, objs));
		}
	}

	// 断言对象和属性的非空
	private static boolean assertNonNullField(Object obj, String[] fieldNonNulls) throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException {
		if (null == obj) {
			return false;
		}
		Field[] fields = Class.forName(obj.getClass().getName()).getDeclaredFields();
		if (null == fields || fields.length <= 0) {
			return false;
		}
		List<String> list = new ArrayList<String>();
		for (Field field : fields) {
			field.setAccessible(true);
			Object object = field.get(obj);
			if (object != null) {
				if (object instanceof String) {
					if (isEmpty((String) object)) {
						continue;
					}
				}
				list.add(field.getName());
			}
		}
		if (null == list || list.isEmpty()) {
			return false;
		}
		return list.containsAll(Arrays.asList(fieldNonNulls));
	}

	// 断言对象是否为空
	private static boolean assertNonNullObj(Object obj, String error, Integer messageCode, Object[] objs) throws WebException {
		if (obj instanceof String) {
			String str = (String) obj;
			if (!isEmpty(str)) {
				return true;
			}
		} else {
			if (obj != null) {
				return true;
			}
		}
		errorHandler(error, messageCode, objs);
		return false;
	}


 

}
